﻿using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;
using System.Text;

namespace Snowdreamist.Collection
{
    public class ObservableThreadSafeDictionary<TKey, TValue> : ThreadSafeDictionary<TKey, TValue>, INotifyCollectionChanged
    {
        public override void Add(KeyValuePair<TKey, TValue> item)
        {
            base.Add(item);
            // notify
            this.OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, item.Key));
        }

        public override void Add(TKey key, TValue value)
        {
            base.Add(key, value);
            // notify
            this.OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, key));
        }

        public override bool TryAdd(TKey key, Func<TValue> valueFunc)
        {
            var r = base.TryAdd(key, valueFunc);
            if (r)
            {
                // notify
                this.OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, key));
            }
            return r;
        }

        public override bool TryAdd(TKey key, TValue value)
        {
            var r = base.TryAdd(key, value);
            if (r)
            {
                // notify
                this.OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, key));
            }
            return r;
        }

        public override TValue GetOrAdd(TKey key, Func<TValue> valueFunc)
        {
            if (valueFunc == null)
                throw new ArgumentNullException("valueFunc");

            TValue value = default(TValue);
            if (this.GetOrAdd(key, valueFunc, out value))
            {
                // notify
                this.OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, key));
            }

            return value;
        }

        public override void Clear()
        {
            base.Clear();
            // notify
            this.OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
        }

        public override bool Remove(KeyValuePair<TKey, TValue> item)
        {
            var r = base.Remove(item);
            if (r)
            {
                // notify
                this.OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, item.Key));
            }
            return r;
        }

        public override bool Remove(TKey key)
        {
            var r = base.Remove(key);
            if (r)
            {
                // notify
                this.OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, key));
            }
            return r;
        }

        public override TValue this[TKey key]
        {
            get
            {
                return base[key];
            }
            set
            {
                base[key] = value;
                // notify
                this.OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Replace, key, key));
            }
        }

        protected virtual void OnCollectionChanged(NotifyCollectionChangedEventArgs eventArgs)
        {
            if (eventArgs == null)
                return;
            if (this.CollectionChanged != null)
                this.CollectionChanged(this, eventArgs);
        }

        public event NotifyCollectionChangedEventHandler CollectionChanged;
    }
}